<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>formData上传 + 大文件分片 + 上传进度</title>
    <style>
        #progress{
            display: none;
        }
        .outer{
            background-color: darkgray;
            height: 12px;
            width: 300px;
            float: left;
        }
        .inner{
            background-color: green;
            height: 12px;
            width: 0;
        }
        .rate{
            font-size: 12px;
            float: left;
        }
    </style>
</head>
<body>
    <h1>formData上传 + 上传进度</h1>
    <input id="file" type="file" value="请选择文件" onchange="fileChange();">
    <input type="button" value="上传" onclick="upload();">
    <div id="progress">
        <!--<div class="outer">
            <div class="inner"></div>
        </div>
        <span class="rate"></span>-->
    </div>
    <script src="jquery.min.js"></script>
    <script>

        let totalSize = 0;
        var arr = [];
        var uploadCheckInterval;
        var fileKey;

        $(function(){
            //alert(1);
        })

        function fileChange(){
            $("#progress").hide();
            $(".inner").css("width", 0);
        }

        function upload(){

            //debugger;
            arr = [];
            var myFile = $("#file")[0].files[0];

            const LENGTH = 1024 * 1024 * 1; //每片1M
            let chunks = slice(myFile, LENGTH); // 首先拆分切片

            totalSize = myFile.size;

            fileKey = new Date().getTime();

            for(var i = 0; i < chunks.length; i++){
                var formData = new FormData();
                formData.append("file", chunks[i]);
                formData.append("fileKey", fileKey);
                formData.append("fileName", myFile.name);
                formData.append("fileIndex", i);
                var str = "";
                str += `<div id="`+ `outer` + i +`" class="outer">
                                <div id="`+ `inner` + i +`" class="inner"></div>
                            </div>
                            <span id="`+ `rate` + i +`" class="rate">0%</span>
                            <div style="clear: left"></div>`;
                $("#progress").append(str);
                $.ajax({
                    type: "POST",
                    url: '/formDataProgressPiece/upload',
                    data: formData,
                    contentType: false, //必须
                    processData: false, //必须
                    //dataType: "json",
                    xhr: function(){
                        var ii = i;
                        $("#progress").show();

                        let xhr = new XMLHttpRequest();

                        xhr.upload.addEventListener('progress', function (e) {
                            let loaded = e.loaded;
                            let total = e.total;
                            var rate = (loaded/total) * 100;
                            console.log(e, '上传', rate + '%', ii);
                            $("#inner"+ii).css("width", loaded / total * 300 + "px" );
                            $("#rate"+ii).html(Math.floor(rate) + '%');
                        })

                        return xhr;
                    },
                    success: function(res){

                        // console.log("success");
                        // console.log(res);
                        var fileIndex = res.fileIndex;
                        var fileSize = res.fileSize;
                        arr[fileIndex] = fileSize;
                        //清空上传文件的值
                        // $('#file').val('');
                        //$('#success_image').attr('src', res.realPathList[0]);
                    },
                    error : function(res) {
                        // console.log("error");
                        // console.log(res);
                        //清空上传文件的值
                        //$('#file').val('');
                    }
                })
            }

            uploadCheckInterval = self.setInterval("uploadCheck()",1000);
        }

        function slice(file, piece = 1024 * 1024 * 5) {

            let totalSize = file.size; // 文件总大小

            let start = 0; // 每次上传的开始字节

            let end = start + piece; // 每次上传的结尾字节

            let chunks = []

            while (start < totalSize) {

                // 根据长度截取每次需要上传的数据

                // File对象继承自Blob对象，因此包含slice方法

                let blob = file.slice(start, end);

                chunks.push(blob)

                start = end;

                end = start + piece;

            }

            return chunks

        }

        function uploadCheck() {
            var sum = 0;
            for (var i = 0; i < arr.length; i++){
                sum += arr[i];
            }

            if(sum === totalSize){
                clearInterval(uploadCheckInterval);
                $.post("/formDataProgressPiece/mergeFile",
                    {
                        "fileKey": fileKey
                    }, function (res) {
                        console.log(res);
                        alert("上传完毕");
                        $("#progress").html("");
                        $('#file').val('');
                    })
            }
        }
    </script>
</body>
</html>